#include <fermat/common/this_thread.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>

namespace fermat {
namespace this_thread{
	  __thread pthread_t t_tid = 0;
	
  
    void setThreadName(pthread_t thread, const std::string &threadName)
    {
		if (::pthread_setname_np(thread, threadName.c_str()) == ERANGE && threadName.size() > 15) {
			std::string truncName(threadName, 0, 7);
			truncName.append("~");
			truncName.append(threadName, threadName.size() - 7, 7);
			pthread_setname_np(thread, truncName.c_str());
		}
    }
	void cacheTid()
	{
	  if (t_tid == 0) {
	    	t_tid = static_cast<pthread_t>( syscall (SYS_gettid) );
	  }
	}
	bool isMainThread()
	{
 		  return tid() == (pthread_t)::getpid();
	}
		
	void exit()
	{
		::pthread_exit(NULL);
	}
		
	void yield()
	{
		::sched_yield();
	}

	bool sleep_for(Timespan span)
	{

		struct timespec ts = { 0, 0 };
		ts.tv_sec = static_cast<time_t>(span.totalSeconds());
		ts.tv_nsec = static_cast<long>(span.useconds() * 1000);
		::nanosleep(&ts, NULL);

	return true;

	}

	bool sleep_until(Timestamp stamp)
	{
		Timestamp now;
		if(now >= stamp) {
			return false;
		} 
		Timespan span = now -stamp;
		return  sleep_for(span);
	}

}


}
